package com.ibiaoke.order.service;

import com.ibiaoke.common.configs.AliPayConfigs;
import com.ibiaoke.common.configs.AppAliPayConfigs;
import com.ibiaoke.common.configs.GlobalConfigs;
import com.ibiaoke.common.configs.GlobalConfigsKey;
import com.ibiaoke.common.consts.BusinessDef;
import com.ibiaoke.common.utils.AssertUtils;
import com.ibiaoke.common.utils.CashUtil;
import com.ibiaoke.common.utils.DateUtils;
import com.ibiaoke.common.utils.SmsUtil;
import com.ibiaoke.customer.consts.PayTypeConst;
import com.ibiaoke.customer.consts.TradeTypeConsts;
import com.ibiaoke.customer.entity.Customer;
import com.ibiaoke.customer.service.DepositRecorderService;
import com.ibiaoke.customer.service.DepositService;
import com.ibiaoke.order.consts.OrderStatusConst;
import com.ibiaoke.order.dao.OrderDao;
import com.ibiaoke.order.dao.XcxOrderDao;
import com.ibiaoke.order.entity.Order;
import com.ibiaoke.order.entity.XcxOrder;
import com.ibiaoke.pay.AppAliPay;
import com.ibiaoke.pay.AppWeChatPayClient;
import com.ibiaoke.pay.BkAliPayClient;
import com.ibiaoke.pay.BkWeChatPayClient;
import com.ibiaoke.system.dao.ShopDao;
import com.ibiaoke.system.entity.Shop;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;
import java.util.Map;

@Service
public class OrderPayServiceImpl implements OrderPayService {

    private Logger logger = Logger.getLogger(this.getClass().getName());

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private ShopDao shopDao;

    @Autowired
    private BkWeChatPayClient bkWeChatPayClient;

    @Autowired
    private AppWeChatPayClient appWeChatPayClient;

    @Autowired
    private BkAliPayClient bkAliPayClient;

    @Autowired
    private AppAliPay appAliPay;

    @Autowired
    private DepositService depositService;

    @Autowired
    private DepositRecorderService depositRecorderService;

    @Autowired
    private XcxOrderDao xcxOrderDao;

    @Autowired
    private XcxPayOrderService xcxPayOrderService;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, String> payOrderByWeChat(Integer orderId, String openId) {
        AssertUtils.notNull(orderId, "请选择订单");
        Order order = orderService.getOrder(orderId);
        validate(order);
        String body = "让我来果源订单：" + order.getOrderCode();
        String out_trade_no = order.getOrderCode();
        String total_fee = String.valueOf(CashUtil.getCent(order.getOrderPrice()));
        String trade_type = "JSAPI";
        String notify_url = GlobalConfigs.getConfigure(GlobalConfigsKey.WeChat.NOTIFY_URL);
        notify_url = notify_url.replace("BUSINESS_TYPE", BusinessDef.PAY_ORDER);
        return bkWeChatPayClient.wxPay(openId, body, out_trade_no, total_fee, trade_type, notify_url);
    }

    /**
     * App微信支付
     * @param orderId
     * @return
     */
    @Transactional
    @Override
    public Map<String, Object> payOrderByAppWeChat(Integer orderId,String ip) {
        AssertUtils.notNull(orderId, "请选择订单");
        Order order = orderService.getOrder(orderId);
        validate(order);
        String body = "让我来果源订单：" + order.getOrderCode();
        String out_trade_no = order.getOrderCode();
        String total_fee = String.valueOf(CashUtil.getCent(order.getOrderPrice()));
        String trade_type = "APP";
        String notify_url = GlobalConfigs.getConfigure(GlobalConfigsKey.WeChat.NOTIFY_URL);
        notify_url = notify_url.replace("BUSINESS_TYPE", BusinessDef.WX_PAY_ORDER);
        return appWeChatPayClient.appWxPay(body,out_trade_no,total_fee,trade_type,notify_url,ip);
    }

    @Transactional
    @Override
    public String payOrderByAliPay(Integer orderId) {
        AssertUtils.notNull(orderId, "请选择订单");
        Order order = orderService.getOrder(orderId);
        validate(order);
        //商户订单号
        String out_trade_no = order.getOrderCode();
        String subject = "让我来果源订单:" + out_trade_no;
        String total_amount = order.getOrderPrice() + "";
        String notify_url = AliPayConfigs.getNotifyURL();
        notify_url = notify_url.replace("BUSINESS_TYPE", BusinessDef.PAY_ORDER);
        String return_url = AliPayConfigs.getReturnURL();
        return bkAliPayClient.aliPay(out_trade_no, subject, total_amount, notify_url, return_url);
    }

    @Transactional
    @Override
    public String payOrderByAppAliPay(Integer orderId) {
        AssertUtils.notNull(orderId, "请选择订单");
        Order order = orderService.getOrder(orderId);
        validate(order);
        //商户订单号
        String total_amount = order.getOrderPrice().toString();
        Map<String, Object> body = new Hashtable<String, Object>();
        body.put("out_trade_no", order.getOrderCode());
        body.put("subject", "让我来果源订单:" + order.getOrderCode());
        body.put("total_amount", total_amount);
        String notify_url = AliPayConfigs.getNotifyURL();
        notify_url = notify_url.replace("BUSINESS_TYPE", BusinessDef.PAY_ORDER);
        //body.put("notify_url", AppAliPayConfigs.getNotifyURL().replace("BUSINESS_TYPE", BusinessDef.PAY_ORDER));
        body.put("notify_url",notify_url);
        body.put("return_url",  AppAliPayConfigs.getReturnURL());
        return appAliPay.aliPay(total_amount,body);
    }


    @Override
    public void validate(Order order) {
        AssertUtils.notNull(order, "请选择支付订单");
        AssertUtils.requireEquals(order.getOrderStatus(), OrderStatusConst.UNPAID, "订单已支付");
        AssertUtils.requireTrue(order.getOrderPrice().compareTo(new BigDecimal("0.01")) >= 0,
                "支付金额不能小于0.01元");
        AssertUtils.requireTrue(order.getCreateTime().after(DateUtils.add(Calendar.HOUR,-1))
                ,"订单超时，不能支付");
    }

    /**
     * 账户余额支付
     * @param orderId
     * @param customer
     * @param smsCode
     */
    @Override
    @Transactional
    public void payOrderByDepositPay(Integer orderId, Customer customer, String smsCode) {
        AssertUtils.notNull(orderId, "请选择支付订单");
        AssertUtils.notBlank(smsCode, "验证码不能为空");
        Order order = orderDao.selectByPrimaryKey(orderId);
        validate(order);
        SmsUtil.validateMobileCode(customer.getCustomerMobile(), smsCode);
        int i = depositService.payOrder(customer.getCustomerId(), order.getOrderPrice());
        if (i > 0) {
            depositRecorderService.insert(customer.getCustomerId(), PayTypeConst.DEPOSIT, order.getOrderCode(),
                    TradeTypeConsts.CONSUME, order.getOrderPrice());
            orderService.payOrder(order.getOrderCode(), PayTypeConst.DEPOSIT);
        }
    }

    /**
     * 门店自提的余额支付
     * @param shopId
     * @param cash
     * @param customer
     * @param smsCode
     */
    @Override
    public void offLinePayByDeposit(Integer shopId, BigDecimal cash,Customer customer, String smsCode) {
        AssertUtils.notNull(shopId, "请选择店铺");
        AssertUtils.notNull(cash, "请输入金额");
        Shop shop = shopDao.selectByPrimaryKey(shopId);
        AssertUtils.notNull(shop,"店铺不存在");
        AssertUtils.requireTrue(cash.compareTo(new BigDecimal(10000000))<0,"请输入实际金额");

        Order order = new Order();
        order.setShopId(shopId);                            //店铺编号
        order.setDeliveryType(1);                           //订单类型：自提
        order.setUserId(customer.getCustomerId());                            //用户编号
        order.setOrderPrice(cash);      //订单金额
        order.setDeliveryAddress(shop.getShopAddress());    //店铺地址
        order.setExpressPrice(BigDecimal.valueOf(0));       //订单运费

        //订单经纬度(店铺经纬度)
        order.setLongitude(shop.getDesLongitude());
        order.setLatitude(shop.getDesLatitude());

        order.setCreateTime(new Date());                    //订单创建时间
        order.setUpdateTime(new Date());                    //订单修改时间
        order.setSource("DEPOSIT");                          //订单来源
        order.setContactMobile(customer.getCustomerMobile());
        order.setContactPersion(customer.getCustomerNickname());
        order.setOrderStatus(OrderStatusConst.UNPAID);

        String orderNo = orderService.generateOrderNo();    //10位系统时间戳+4位的随机数作为订单号
        order.setOrderCode(orderNo);                        //订单编号

        orderService.saveOrder(order);                      //创建新的订单

        Order orderInfo = orderService.getOrderInfoByCode(orderNo);//获取订单Id

        payOrderByDepositPay(orderInfo.getOrderId(), customer, smsCode);
    }

    @Override
    public void xcxOffLinePayByDeposit(Integer shopId, BigDecimal cash, Customer customer, String smsCode) {
        AssertUtils.notNull(shopId, "请选择店铺");
        AssertUtils.notNull(cash, "请输入金额");
        Shop shop = shopDao.selectByPrimaryKey(shopId);
        AssertUtils.notNull(shop,"店铺不存在");
        AssertUtils.requireTrue(cash.compareTo(new BigDecimal(10000000))<0,"请输入实际金额");

        XcxOrder order = new XcxOrder();
        order.setShopId(shopId);                            //店铺编号
        order.setDeliveryType(1);                           //订单类型：自提
        order.setUserId(customer.getCustomerId());                            //用户编号
        order.setOrderPrice(cash);      //订单金额
        order.setDeliveryAddress(shop.getShopAddress());    //店铺地址
        order.setExpressPrice(BigDecimal.valueOf(0));       //订单运费
        order.setOrderType(new Byte("3"));                //快捷支付
        order.setPayType(4);                                 //预存款支付
        //订单经纬度(店铺经纬度)
        order.setLongitude(shop.getDesLongitude());
        order.setLatitude(shop.getDesLatitude());

        order.setCreateTime(new Date());                    //订单创建时间
        order.setUpdateTime(new Date());                    //订单修改时间
        order.setEndTime(new Date());
        order.setSource("小程序快捷支付");                          //订单来源
        order.setContactMobile(customer.getCustomerMobile());
        order.setContactPersion(customer.getCustomerNickname());
        order.setOrderStatus(OrderStatusConst.UNPAID);
        order.setDelStatus(new Byte("0"));

        String orderNo = orderService.generateOrderNo();    //10位系统时间戳+4位的随机数作为订单号
        order.setOrderCode(orderNo);                        //订单编号

        xcxOrderDao.saveXcxOrder(order);                      //创建新的订单

        XcxOrder orderInfo = xcxOrderDao.getOrderByOrderCode(order.getOrderCode());//获取订单Id

        xcxPayOrderService.payXcxOrderByDepositPay(orderInfo,smsCode);
    }
}
